package com.yilin.tms.order.service.payment.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.ArrayUtil;
import com.yilin.commons.util.CommonUtil;
import com.yilin.commons.util.DateTimeUtil;
import com.yilin.commons.util.MathUtil;
import com.yilin.tms.core.commons.utils.OrderUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.commons.utils.QueryUtil;
import com.yilin.tms.core.entity.capital.TradeRecord;
import com.yilin.tms.core.entity.order.goods.GoodsOrder;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.payment.OrderRefundCost;
import com.yilin.tms.core.entity.order.rob.RobOrder;
import com.yilin.tms.core.entity.order.clearing.ClearingDetail;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.user.RoleType;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.order.mapper.payment.OrderPaymentCostMapper;
import com.yilin.tms.order.service.payment.IOrderPaymentCostService;
import com.yilin.tms.order.service.payment.IOrderRefundCostService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 预付单创建，预付单和订单绑定，货主可用
 * 预付单用于记录货主订单支付链数据
 * 可以同时支付多条预付单
 * 预付单不是支付交易记录
 * 汇总清算结束会生成多条预付单
 * 清算反审核退回时：
 */
@Service
@Transactional
public class OrderPaymentCostService extends ServiceImpl<OrderPaymentCostMapper, OrderPaymentCost> implements IOrderPaymentCostService {

    private static Logger logger = LoggerFactory.getLogger(OrderPaymentCostService.class);

    @Resource
    private OrderPaymentCostMapper orderPaymentCostMapper;
    @Resource
    private IOrderRefundCostService orderRefundCostService;

    /**
     * 通知支付结果 交易
     */
    @Override
    public void updateOrderPaymentResult(TradeRecord tradeRecord, Account loginUser) {
        List<TradeRecord.TradeStatus> statusList = ArrayUtil.initList(TradeRecord.TradeStatus.paySuccess, TradeRecord.TradeStatus.payFail, TradeRecord.TradeStatus.create, TradeRecord.TradeStatus.close);
        if (!statusList.contains(tradeRecord.getTradeStatus())) throw new BusinessException("支付结果状态有误！");
        String[] orderPaymentIds = tradeRecord.getOrderPaymentIds().split(",");
        List<OrderPaymentCost> paymentCostList = orderPaymentCostMapper.selectBatchIds(ArrayUtil.initList(orderPaymentIds));
        paymentCostList.forEach(orderPayment -> {
            if (orderPayment.getPayStatus() == OrderPaymentCost.PayStatus.complete) throw new BusinessException("订单已经支付完成...");
            /// 分别在成功，创建，关闭+失败时更新状态
            if (tradeRecord.getTradeStatus() == TradeRecord.TradeStatus.paySuccess) {
                orderPayment.setBankFlowNo(tradeRecord.getBankFlowNo());
                orderPayment.setPayCompleteTime(tradeRecord.getFinishTime());
                orderPayment.setPayStatus(OrderPaymentCost.PayStatus.complete);
                orderPayment.setPaymentTypeName(tradeRecord.getPayType().name+tradeRecord.getBankType().name);
                orderPayment.setPaymentCapitalAccount(tradeRecord.getPaymentCapitalAccount());
                orderPayment.setIncomeCapitalAccount(tradeRecord.getIncomeCapitalAccount());
                orderPayment.setOptUserId(tradeRecord.getOptUserId());
                orderPayment.setOptUserName(tradeRecord.getOptUserName());
                orderPayment.setBankFlowNo(tradeRecord.getBankFlowNo());
                orderPayment.setPayType(tradeRecord.getPayType());
            } else if (tradeRecord.getTradeStatus() == TradeRecord.TradeStatus.create) {
                orderPayment.setPayInitiateTime(new Date());
                orderPayment.setPayStatus(OrderPaymentCost.PayStatus.wait);
                orderPayment.setInitiateUserId(loginUser == null ? null : loginUser.getId());
                orderPayment.setInitiateUserName(loginUser == null ? null : loginUser.getName());
                orderPayment.setTradeNo(tradeRecord.getTradeNo());
            } else {//失败/关闭时，恢复预支付单状态
                orderPayment.setPayStatus(OrderPaymentCost.PayStatus.create);
                orderPayment.setTradeNo(null);
            }
            orderPaymentCostMapper.updateById(orderPayment);
        });
    }

    /**
     * 取消预付订单
     */
    @Override
    public void cancelOrderPayment(String orderPaymentId, Account loginUser) {
        OrderPaymentCost orderPaymentCost = orderPaymentCostMapper.selectById(orderPaymentId);
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.cancel);
        orderPaymentCost.setOptUserId(loginUser.getId());
        orderPaymentCost.setOptUserName(loginUser.getName());
        orderPaymentCostMapper.updateById(orderPaymentCost);
    }

    /**
     * 生成发布支付单
     * 货源保存成功时生成支付单
     */
    @Override
    public OrderPaymentCost generateGoodsOrderPayment(GoodsOrder goodsOrder) {
        OrderPaymentCost orderPaymentCost = getOrderPaymentByGoodsOrderId(goodsOrder.getId());
        if (orderPaymentCost != null) return orderPaymentCost;
        //### 创建信息支付单
        orderPaymentCost = new OrderPaymentCost();
        orderPaymentCost.setPrePaymentNo(DateTimeUtil.dateNo("YF"));
//        orderPaymentCost.setPlatId(goodsOrder.getPlatId());
//        orderPaymentCost.setPlatName(goodsOrder.getPlatName());
//        orderPaymentCost.setZonePlatId(goodsOrder.getZonePlatId());
//        orderPaymentCost.setZonePlatName(goodsOrder.getZonePlatName());
        orderPaymentCost.setShipperAccountId(goodsOrder.getShipperAccountId());
        orderPaymentCost.setShipperAccountName(goodsOrder.getShipperAccountName());
        orderPaymentCost.setShipperOrganizeId(goodsOrder.getShipperOrganizeId());
        orderPaymentCost.setShipperOrganizeName(goodsOrder.getShipperOrganizeName());
        orderPaymentCost.setGoodsOrderId(goodsOrder.getId());
        orderPaymentCost.setGoodsOrderNo(goodsOrder.getGoodsOrderNo());
        orderPaymentCost.setMatchmaking(goodsOrder.getMatching());
        orderPaymentCost.setIncludedTax(goodsOrder.getIncludedTax());

        orderPaymentCost.setPaySite(OrderPaymentCost.PaySite.release);
        orderPaymentCost.setSettlementType(getAutSettlementType(goodsOrder.getSettlementType(), OrderPaymentCost.PaySite.release));
        //-设置支付配率
        orderPaymentCost.setReleasePaymentRate(goodsOrder.getReleasePaymentRate());
        orderPaymentCost.setRobPaymentRate(goodsOrder.getRobPaymentRate());
        orderPaymentCost.setDeliverPaymentRate(goodsOrder.getDeliverPaymentRate());
        orderPaymentCost.setArrivalPaymentRate(goodsOrder.getArrivalPaymentRate());
        //-设置费率
        orderPaymentCost.setShipperTaxRate(goodsOrder.getShipperTaxRate());
        orderPaymentCost.setShipperFeeRate(goodsOrder.getShipperFeeRate());
        orderPaymentCost.setInsuranceRate(goodsOrder.getInsuranceRate());
        //-真实保单费用
        Double insuranceCost = MathUtil.multiply(orderPaymentCost.getSplitInsuranceAmount(), orderPaymentCost.getInsuranceRate(),2);
        orderPaymentCost.setSplitInsuranceCost(insuranceCost);
        //-设置费用列表[货单提供]
        orderPaymentCost.setSplitInsuranceAmount(goodsOrder.getInsuredAmount());
        orderPaymentCost.setSplitAdditionalCost(goodsOrder.getShipperAdditionalCost());
        //-设置运输费及其他费用
        orderPaymentCost.setTransportCost(goodsOrder.getShipperTransportCost());
        setOrderPaymentCost(orderPaymentCost);
        //-设置阶段必须支付费用
        setPayAutCost(orderPaymentCost, orderPaymentCost.getReleasePaymentRate());
        orderPaymentCost.setPayCreateTime(new Date());
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.none);
        orderPaymentCost.setPayRemark(String.format("订单发布阶段合计费用%s元，本次支付比例%s",
                CommonUtil.formatDoubleTwo(orderPaymentCost.getActualTotalCost()),
                CommonUtil.formatDoubleTwo(orderPaymentCost.getReleasePaymentRate() * 100) + "%"));
        if (orderPaymentCost.getPayCost() > 0) orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.create);
        orderPaymentCostMapper.insert(orderPaymentCost);
        return orderPaymentCost;
    }

    /**
     * 生成抢单支付单
     * 每审核成功一个抢单生成一个支付单
     */
    @Override
    public OrderPaymentCost generateRobOrderPayment(RobOrder robOrder, GoodsOrder goodsOrder) {
        OrderPaymentCost orderPaymentCost = getOrderPaymentByRobOrderId(robOrder.getId());
        if (orderPaymentCost != null) return orderPaymentCost;
        //### 获取货单源支付单
        OrderPaymentCost goodsOrderPaymentCost = getOrderPaymentByGoodsOrderId(goodsOrder.getId());
        //### 创建信息支付单
        orderPaymentCost = new OrderPaymentCost();
//        orderPaymentCost.setPlatId(robOrder.getPlatId());
//        orderPaymentCost.setPlatName(robOrder.getPlatName());
//        orderPaymentCost.setZonePlatId(robOrder.getZonePlatId());
//        orderPaymentCost.setZonePlatName(robOrder.getZonePlatName());
        orderPaymentCost.setPrePaymentNo(DateTimeUtil.dateNo("YF"));
        orderPaymentCost.setRobOrderId(robOrder.getId());
        orderPaymentCost.setRobOrderNo(robOrder.getRobOrderNo());
        orderPaymentCost.setShipperAccountId(robOrder.getShipperAccountId());
        orderPaymentCost.setShipperAccountName(robOrder.getShipperAccountName());
        orderPaymentCost.setShipperOrganizeId(robOrder.getShipperOrganizeId());
        orderPaymentCost.setShipperOrganizeName(robOrder.getShipperOrganizeName());
        orderPaymentCost.setGoodsOrderId(goodsOrderPaymentCost.getGoodsOrderId());
        orderPaymentCost.setMatchmaking(goodsOrderPaymentCost.getMatchmaking());
        orderPaymentCost.setIncludedTax(goodsOrderPaymentCost.getIncludedTax());
        orderPaymentCost.setInitiateUserId(goodsOrderPaymentCost.getInitiateUserId());
        orderPaymentCost.setInitiateUserName(goodsOrderPaymentCost.getInitiateUserName());
        orderPaymentCost.setPaySite(OrderPaymentCost.PaySite.robSuccess);
        orderPaymentCost.setSettlementType(getAutSettlementType(goodsOrder.getSettlementType(), OrderPaymentCost.PaySite.robSuccess));
        //继承费率，配率
        extendsOrderPaymentRate(orderPaymentCost, goodsOrderPaymentCost);
        //-更新拆分费用
        orderPaymentCost.setSplitInsuranceCost(CommonUtil.doubleTwo(robOrder.getInsuredCost()));
        orderPaymentCost.setSplitInsuranceAmount(CommonUtil.doubleTwo(robOrder.getInsuredAmount()));
        orderPaymentCost.setSplitAdditionalCost(CommonUtil.doubleTwo(robOrder.getAdditionalCost()));
        orderPaymentCost.setSplitAlreadyPayCost(CommonUtil.doubleTwo(robOrder.getPayCost()));
        //-运输费
        orderPaymentCost.setTransportCost(robOrder.getRobTransportCost());
        setOrderPaymentCost(orderPaymentCost);
        //-设置阶段必须支付费用
        setPayAutCost(orderPaymentCost, orderPaymentCost.getRobPaymentRate());
        orderPaymentCost.setPayCreateTime(new Date());
        orderPaymentCost.setPayRemark(String.format("订单抢单阶段合计费用%s元，本次支付比例%s",
                CommonUtil.formatDoubleTwo(orderPaymentCost.getActualTotalCost()),
                CommonUtil.formatDoubleTwo(orderPaymentCost.getReleasePaymentRate() * 100) + "%"));
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.none);
        if (orderPaymentCost.getPayCost() > 0) orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.create);
        orderPaymentCostMapper.insert(orderPaymentCost);
        return orderPaymentCost;
    }

    /**
     * 生成运单发货支付单
     * 货主发货时创建
     */
    @Override
    public OrderPaymentCost generateDeliveryOrderPayment(TransitOrder transitOrder, RobOrder robOrder) {
        OrderPaymentCost orderPaymentCost = getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.delivery);
        if (orderPaymentCost != null) return orderPaymentCost;
        //### 获取抢单源支付单
        OrderPaymentCost robOrderPaymentCost = getOrderPaymentByRobOrderId(robOrder.getId());
        //### 创建信息支付单
        orderPaymentCost = new OrderPaymentCost();
//        orderPaymentCost.setPlatId(transitOrder.getPlatId());
//        orderPaymentCost.setPlatName(transitOrder.getPlatName());
//        orderPaymentCost.setZonePlatId(transitOrder.getZonePlatId());
//        orderPaymentCost.setZonePlatName(transitOrder.getZonePlatName());
        orderPaymentCost.setShipperAccountId(transitOrder.getShipperAccountId());
        orderPaymentCost.setShipperAccountName(transitOrder.getShipperAccountName());
        orderPaymentCost.setShipperOrganizeId(transitOrder.getShipperOrganizeId());
        orderPaymentCost.setShipperOrganizeName(transitOrder.getShipperOrganizeName());
        orderPaymentCost.setTransitOrderId(transitOrder.getId());
        orderPaymentCost.setTransportNo(transitOrder.getTransportNo());
        orderPaymentCost.setGoodsOrderId(robOrderPaymentCost.getGoodsOrderId());
        orderPaymentCost.setRobOrderId(robOrder.getId());
        orderPaymentCost.setPrePaymentNo(DateTimeUtil.dateNo("YF"));
        orderPaymentCost.setMatchmaking(robOrderPaymentCost.getMatchmaking());
        orderPaymentCost.setIncludedTax(robOrderPaymentCost.getIncludedTax());
        orderPaymentCost.setInitiateUserId(robOrderPaymentCost.getInitiateUserId());
        orderPaymentCost.setInitiateUserName(robOrderPaymentCost.getInitiateUserName());
        orderPaymentCost.setSettlementType(transitOrder.getSettlementType());
        orderPaymentCost.setPaySite(OrderPaymentCost.PaySite.delivery);
        orderPaymentCost.setSettlementType(getAutSettlementType(robOrder.getSettlementType(), OrderPaymentCost.PaySite.delivery));
        //继承费率，配率
        extendsOrderPaymentRate(orderPaymentCost, robOrderPaymentCost);
        //-开始拆分费用 注意：只能用分配量拆分
        orderPaymentCost.setSplitInsuranceCost(transitOrder.getInsuredCost());
        orderPaymentCost.setSplitInsuranceAmount(transitOrder.getInsuredAmount());
        orderPaymentCost.setSplitAdditionalCost(transitOrder.getAdditionalCost());
        //-发货前已支付费用 支付成功后需要累加 只是货单+抢单时支付拆分费用
        orderPaymentCost.setSplitAlreadyPayCost(transitOrder.getAssignPayCost());
        //-运输费
        orderPaymentCost.setTransportCost(OrderUtil.getTransCostBySettleType(orderPaymentCost.getSettlementType(), transitOrder));
        setOrderPaymentCost(orderPaymentCost);
        //-设置阶段必须支付费用
        setPayAutCost(orderPaymentCost, orderPaymentCost.getDeliverPaymentRate());
        orderPaymentCost.setPayRemark(String.format("订单发货阶段合计费用%s元，本次支付比例%s",
                CommonUtil.formatDoubleTwo(orderPaymentCost.getActualTotalCost()),
                CommonUtil.formatDoubleTwo(orderPaymentCost.getReleasePaymentRate() * 100) + "%"));
        orderPaymentCost.setPayCreateTime(new Date());
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.none);
        if (orderPaymentCost.getPayCost() > 0) orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.create);
        orderPaymentCostMapper.insert(orderPaymentCost);
        return orderPaymentCost;
    }

    /**
     * 生成运单收货支付单
     * 司机送达时创建
     */
    @Override
    public OrderPaymentCost generateReceiptOrderPayment(TransitOrder transitOrder) {
        OrderPaymentCost orderPaymentCost = getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.receipt);
        if (orderPaymentCost != null) return orderPaymentCost;
        //### 获取抢单源支付单
        OrderPaymentCost deliveryOrderPaymentCost = getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.delivery);
        //### 创建信息支付单
//        orderPaymentCost = new OrderPaymentCost();
//        orderPaymentCost.setZonePlatId(transitOrder.getZonePlatId());
//        orderPaymentCost.setZonePlatName(transitOrder.getZonePlatName());
//        orderPaymentCost.setPlatId(transitOrder.getPlatId());
//        orderPaymentCost.setPlatName(transitOrder.getPlatName());
        orderPaymentCost.setShipperAccountId(transitOrder.getShipperAccountId());
        orderPaymentCost.setShipperAccountName(transitOrder.getShipperAccountName());
        orderPaymentCost.setShipperOrganizeId(transitOrder.getShipperOrganizeId());
        orderPaymentCost.setShipperOrganizeName(transitOrder.getShipperOrganizeName());
        orderPaymentCost.setSettlementType(transitOrder.getSettlementType());
        orderPaymentCost.setTransitOrderId(deliveryOrderPaymentCost.getTransitOrderId());
        orderPaymentCost.setTransportNo(transitOrder.getTransportNo());
        orderPaymentCost.setPrePaymentNo(DateTimeUtil.dateNo("YF"));
        orderPaymentCost.setGoodsOrderId(deliveryOrderPaymentCost.getGoodsOrderId());
        orderPaymentCost.setRobOrderId(deliveryOrderPaymentCost.getRobOrderId());
        orderPaymentCost.setMatchmaking(deliveryOrderPaymentCost.getMatchmaking());
        orderPaymentCost.setIncludedTax(deliveryOrderPaymentCost.getIncludedTax());
        orderPaymentCost.setInitiateUserId(deliveryOrderPaymentCost.getInitiateUserId());
        orderPaymentCost.setInitiateUserName(deliveryOrderPaymentCost.getInitiateUserName());
        orderPaymentCost.setPaySite(OrderPaymentCost.PaySite.receipt);
        orderPaymentCost.setSettlementType(getAutSettlementType(transitOrder.getSettlementType(), OrderPaymentCost.PaySite.receipt));
        //继承费率，配率
        extendsOrderPaymentRate(orderPaymentCost, deliveryOrderPaymentCost);
        //-引用拆分费用
        orderPaymentCost.setSplitInsuranceCost(deliveryOrderPaymentCost.getSplitInsuranceCost());
        orderPaymentCost.setSplitInsuranceAmount(deliveryOrderPaymentCost.getSplitInsuranceAmount());
        orderPaymentCost.setSplitAdditionalCost(deliveryOrderPaymentCost.getSplitAdditionalCost());
        //-收货前已支付费用 不含收货
        Double alreadyPayCost = MathUtil.add(deliveryOrderPaymentCost.getSplitAlreadyPayCost(), deliveryOrderPaymentCost.getPayCost());
        orderPaymentCost.setSplitAlreadyPayCost(alreadyPayCost);
        //-运输费
        orderPaymentCost.setTransportCost(OrderUtil.getTransCostBySettleType(orderPaymentCost.getSettlementType(), transitOrder));
        setOrderPaymentCost(orderPaymentCost);
        //### 阶段必须支付费用
        if (!transitOrder.getHandLiquidation()) {
            //情况1：自动清算的情况，必须在收货付款前完成全部支付
            if (orderPaymentCost.getSplitAlreadyPayCost() > orderPaymentCost.getActualTotalCost()) {
                //情况1-1：已支付费用已经超出了需支付总费用 形成退款单
                orderPaymentCost.setPayRemark("订单已支付费用超出了需支付总费用，已生成退款单，请等待退款审核");
                orderPaymentCost.setPayCost(0D);
                Map<OrderPaymentCost, OrderRefundCost> paymentOrderRefundMap = generateReceiptRefundData(orderPaymentCost);
                paymentOrderRefundMap.forEach((originalOrderPaymentCost, preOrderRefundCost) -> {
                    OrderRefundCost orderRefundCost = orderRefundCostService.generateOrderRefund(originalOrderPaymentCost, preOrderRefundCost);
                    logger.info(String.format("%s，退款总金额：%s", orderRefundCost.getRefundRemark(), orderRefundCost.getRefundCost()));
                });
            } else {
                //情况1-2：需支付运费剩余全部费用
                orderPaymentCost.setPayRemark("运单自动清算，需支付运费剩余全部费用，请完成支付");
                Double payTotalCost = MathUtil.subtract(orderPaymentCost.getActualTotalCost(), orderPaymentCost.getSplitAlreadyPayCost());
                Double paymentRate = MathUtil.divide(payTotalCost, orderPaymentCost.getActualTotalCost(), 8);
                setPayAutCost(orderPaymentCost, paymentRate);
                if (payTotalCost.doubleValue() != orderPaymentCost.getPayCost()) throw new BusinessException("Cost generating errors!");
            }
        } else {
            //情况2：手动清算，按比例继续付款，剩余款项在手动清算时代扣
            String formatDoubleTwo = CommonUtil.formatDoubleTwo(orderPaymentCost.getArrivalPaymentRate());
            orderPaymentCost.setPayRemark("运单手动清算，本次付款比例" + formatDoubleTwo + "%，剩余费用将在清算后支付");
            setPayAutCost(orderPaymentCost, orderPaymentCost.getArrivalPaymentRate());
        }
        orderPaymentCost.setPayCreateTime(new Date());
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.none);
        if (orderPaymentCost.getPayCost() > 0) orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.create);
        orderPaymentCostMapper.insert(orderPaymentCost);
        return orderPaymentCost;
    }

    /**
     * 生成运单清算支付单
     * 平台清算确认时创建
     */
    @Override
    public OrderPaymentCost generateClearingOrderPayment(TransitOrder transitOrder, ClearingDetail clearingDetail) {
        OrderPaymentCost orderPaymentCost = getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.clearing);
        if (orderPaymentCost != null) return orderPaymentCost;
        //### 获取抢单源支付单
        OrderPaymentCost receiptOrderPaymentCost = getOrderPaymentByTransitOrderId(transitOrder.getId(), OrderPaymentCost.PaySite.receipt);
        //### 创建信息支付单
        orderPaymentCost = new OrderPaymentCost();
        orderPaymentCost.setClearOrderId(clearingDetail.getId());
//        orderPaymentCost.setPlatId(transitOrder.getPlatId());
//        orderPaymentCost.setPlatName(transitOrder.getPlatName());
//        orderPaymentCost.setZonePlatId(transitOrder.getZonePlatId());
//        orderPaymentCost.setZonePlatName(transitOrder.getZonePlatName());
        orderPaymentCost.setPrePaymentNo(DateTimeUtil.dateNo("YF"));
        orderPaymentCost.setPaySite(OrderPaymentCost.PaySite.clearing);
        orderPaymentCost.setSettlementType(transitOrder.getSettlementType());
        orderPaymentCost.setShipperAccountId(transitOrder.getShipperAccountId());
        orderPaymentCost.setShipperAccountName(transitOrder.getShipperAccountName());
        orderPaymentCost.setShipperOrganizeId(transitOrder.getShipperOrganizeId());
        orderPaymentCost.setShipperOrganizeName(transitOrder.getShipperOrganizeName());
        orderPaymentCost.setTransitOrderId(receiptOrderPaymentCost.getTransitOrderId());
        orderPaymentCost.setTransportNo(transitOrder.getTransportNo());
        orderPaymentCost.setGoodsOrderId(receiptOrderPaymentCost.getGoodsOrderId());
        orderPaymentCost.setRobOrderId(receiptOrderPaymentCost.getRobOrderId());
        orderPaymentCost.setMatchmaking(receiptOrderPaymentCost.getMatchmaking());
        orderPaymentCost.setIncludedTax(receiptOrderPaymentCost.getIncludedTax());
        orderPaymentCost.setSettlementType(getAutSettlementType(transitOrder.getSettlementType(), OrderPaymentCost.PaySite.clearing));
        orderPaymentCost.setInitiateUserId(receiptOrderPaymentCost.getInitiateUserId());
        orderPaymentCost.setInitiateUserName(receiptOrderPaymentCost.getInitiateUserName());
        //-设置支付配率
        orderPaymentCost.setReleasePaymentRate(receiptOrderPaymentCost.getReleasePaymentRate());
        orderPaymentCost.setRobPaymentRate(receiptOrderPaymentCost.getRobPaymentRate());
        orderPaymentCost.setDeliverPaymentRate(receiptOrderPaymentCost.getDeliverPaymentRate());
        orderPaymentCost.setArrivalPaymentRate(receiptOrderPaymentCost.getArrivalPaymentRate());
        //-设置费率[采用清算计算的费率]
        orderPaymentCost.setInsuranceRate(clearingDetail.getInsuranceRate());
        orderPaymentCost.setShipperTaxRate(clearingDetail.getShipperTaxRate());
        orderPaymentCost.setShipperFeeRate(clearingDetail.getShipperFeeRate());
        //-设置清算固定费用
        orderPaymentCost.setSplitInsuranceAmount(clearingDetail.getInsuranceAmount());
        orderPaymentCost.setSplitInsuranceCost(clearingDetail.getInsuranceCost());
        orderPaymentCost.setSplitAdditionalCost(clearingDetail.getAdditionalCost());
        //-清算前 已支付费用
        orderPaymentCost.setSplitAlreadyPayCost(clearingDetail.getAlreadyPayCost());
        //-运输费[根据最终结算方式确认运输费]
        orderPaymentCost.setTransportCost(OrderUtil.getTransCostBySettleType(clearingDetail.getActualSettlementType(), transitOrder));
        setOrderPaymentCost(orderPaymentCost);
        //### 阶段必须支付费用
        if (orderPaymentCost.getSplitAlreadyPayCost()==null){
            orderPaymentCost.setSplitAlreadyPayCost(0d);
        }
        if (orderPaymentCost.getSplitAlreadyPayCost() > orderPaymentCost.getActualTotalCost()) {
            //情况1-1：已支付费用已经超出了需支付总费用 形成退款单
            orderPaymentCost.setPayRemark("订单已支付费用超出了需支付总费用，已生成退款单，请等待退款审核");
            orderPaymentCost.setPayCost(0D);
            Map<OrderPaymentCost, OrderRefundCost> paymentOrderRefundMap = generateClearingRefundData(orderPaymentCost);
            paymentOrderRefundMap.forEach((originalOrderPaymentCost, preOrderRefundCost) -> {
                OrderRefundCost orderRefundCost = orderRefundCostService.generateOrderRefund(originalOrderPaymentCost, preOrderRefundCost);
                logger.info(String.format("%s，退款总金额：%s", orderRefundCost.getRefundRemark(), orderRefundCost.getRefundCost()));
            });
        } else {
            //情况1-2：需支付运费剩余全部费用
            orderPaymentCost.setPayRemark("运单已完成，需支付运费剩余全部费用，请完成支付");
            Double payTotalCost = MathUtil.round(MathUtil.subtract(orderPaymentCost.getActualTotalCost(), orderPaymentCost.getSplitAlreadyPayCost()), 2);
            Double paymentRate = MathUtil.divide(payTotalCost, orderPaymentCost.getActualTotalCost(), 8);
            setPayAutCost(orderPaymentCost, paymentRate);
            if (payTotalCost.doubleValue() != orderPaymentCost.getPayCost()) throw new BusinessException("Cost generating errors!");
        }
        orderPaymentCost.setPayCreateTime(new Date());
        orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.none);
        if (orderPaymentCost.getPayCost() > 0) orderPaymentCost.setPayStatus(OrderPaymentCost.PayStatus.create);
        orderPaymentCostMapper.insert(orderPaymentCost);
        return orderPaymentCost;
    }

    @Override
    public OrderPaymentCost getOrderPaymentByGoodsOrderId(String goodsOrderId) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_order_id", goodsOrderId);
        queryWrapper.eq("pay_site", OrderPaymentCost.PaySite.release.index);
        return orderPaymentCostMapper.selectOne(queryWrapper);
    }

    @Override
    public List<OrderPaymentCost> getOrderPaymentByGoodsOrderIds(List<String> goodsOrderIds) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("goods_order_id", goodsOrderIds);
        queryWrapper.eq("pay_site", OrderPaymentCost.PaySite.release.index);
        return orderPaymentCostMapper.selectList(queryWrapper);
    }

    @Override
    public OrderPaymentCost getOrderPaymentByRobOrderId(String robOrderId) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("rob_order_id", robOrderId);
        queryWrapper.eq("pay_site", OrderPaymentCost.PaySite.robSuccess.index);
        return orderPaymentCostMapper.selectOne(queryWrapper);
    }

    @Override
    public List<OrderPaymentCost> getOrderPaymentByRobOrderIds(List<String> robOrderIds) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("rob_order_id", robOrderIds);
        queryWrapper.eq("pay_site", OrderPaymentCost.PaySite.robSuccess.index);
        return orderPaymentCostMapper.selectList(queryWrapper);
    }

    @Override
    public OrderPaymentCost getOrderPaymentByTransitOrderId(String transitOrderId, OrderPaymentCost.PaySite paySite) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transit_order_id", transitOrderId);
        queryWrapper.eq("pay_site", paySite.index);
        return orderPaymentCostMapper.selectOne(queryWrapper);
    }

    @Override
    public List<OrderPaymentCost> getOrderPaymentByTransitOrderIds(List<String> transitOrderIds, OrderPaymentCost.PaySite paySite) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("transit_order_id", transitOrderIds);
        queryWrapper.eq("pay_site", paySite.index);
        return orderPaymentCostMapper.selectList(queryWrapper);
    }

    @Override
    public List<OrderPaymentCost> getOrderPaymentListByTransitOrderId(String transitOrderId) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("transit_order_id", transitOrderId);
        return orderPaymentCostMapper.selectList(queryWrapper);
    }

    //查询分页，顶级和易林可以放开查看
    @Override
    public PageData<OrderPaymentCost> getOrderPaymentPage(OrderPaymentCost query, Account loginUser, Integer page, Integer limit) {
        QueryWrapper<OrderPaymentCost> queryWrapper = new QueryWrapper<>();
//        if (loginUser.getUserType() != UserType.adminUser && loginUser.getUserType() != UserType.yilinUser) {
//            if (loginUser.getUserType() == UserType.zoneUser) {
//                queryWrapper.eq("zone_plat_id", loginUser.getOrganizeId());
//            } else if (loginUser.getUserType() == UserType.platformUser) {
//                queryWrapper.eq("plat_id", loginUser.getOrganizeId());
//            } else {
//                if (loginUser.getRoleType() == RoleType.manager) queryWrapper.eq("shipper_organize_id", loginUser.getOrganizeId());
//                else queryWrapper.eq("shipper_account_id", loginUser.getId());
//            }
//        }
        queryWrapper = QueryUtil.andQueryWrapper(queryWrapper, query);
        return orderPaymentCostMapper.selectPage(new PageData<>(page, limit), queryWrapper);
    }

    @Override
    public List<OrderPaymentCost> getOrderPaymentListByIds(List<String> paymentOrderIds) {
        return orderPaymentCostMapper.selectBatchIds(paymentOrderIds);
    }

    @Override
    public OrderPaymentCost getOrderPaymentById(String paymentOrderId) {
        return orderPaymentCostMapper.selectById(paymentOrderId);
    }

    //公共部分：继承费率，配率
    private void extendsOrderPaymentRate(OrderPaymentCost orderPaymentCost, OrderPaymentCost preOrderPaymentCost) {
        //-设置支付配率
        orderPaymentCost.setReleasePaymentRate(preOrderPaymentCost.getReleasePaymentRate());
        orderPaymentCost.setRobPaymentRate(preOrderPaymentCost.getRobPaymentRate());
        orderPaymentCost.setDeliverPaymentRate(preOrderPaymentCost.getDeliverPaymentRate());
        orderPaymentCost.setArrivalPaymentRate(preOrderPaymentCost.getArrivalPaymentRate());
        //-设置费率
        orderPaymentCost.setShipperFeeRate(preOrderPaymentCost.getShipperFeeRate());
        orderPaymentCost.setShipperTaxRate(preOrderPaymentCost.getShipperTaxRate());
        orderPaymentCost.setInsuranceRate(preOrderPaymentCost.getInsuranceRate());
    }

    //公共部分：设置原费用
    private void setOrderPaymentCost(OrderPaymentCost orderPaymentCost) {
        //-真实额外税费
        orderPaymentCost.setTaxCost(0D);
        if (!orderPaymentCost.getIncludedTax()) {
            Double transitTaxCost = MathUtil.multiply(orderPaymentCost.getTransportCost(), orderPaymentCost.getShipperTaxRate(),2);
            orderPaymentCost.setTaxCost(transitTaxCost);
        }
        //-真实手续费
        orderPaymentCost.setShipperFeeCost(MathUtil.multiply(orderPaymentCost.getTransportCost(), orderPaymentCost.getShipperFeeRate(),2));
        //-真实运输费
        Double actualTransportCost = MathUtil.add(orderPaymentCost.getTransportCost(), orderPaymentCost.getTaxCost());
        orderPaymentCost.setActualTransportCost(actualTransportCost);
        //-最总需支付费用
        orderPaymentCost.setActualTotalCost(MathUtil.add(actualTransportCost,
                orderPaymentCost.getShipperFeeCost(),
                orderPaymentCost.getSplitAdditionalCost(),
                orderPaymentCost.getSplitInsuranceCost()
        ));
    }

    //公共部分：设置实付比例费用
    private void setPayAutCost(OrderPaymentCost orderPaymentCost, Double paymentRate) {
        orderPaymentCost.setPayInsuranceCost(MathUtil.multiply(orderPaymentCost.getSplitInsuranceCost(), paymentRate, 2));
        orderPaymentCost.setPayAdditionalCost(MathUtil.multiply(orderPaymentCost.getSplitAdditionalCost(), paymentRate, 2));
        orderPaymentCost.setPayTransportCost(MathUtil.multiply(orderPaymentCost.getTransportCost(), orderPaymentCost.getReleasePaymentRate(), 2));
        orderPaymentCost.setPayTaxCost(MathUtil.multiply(orderPaymentCost.getTaxCost(), paymentRate, 2));
        orderPaymentCost.setPayShipperFeeCost(MathUtil.multiply(orderPaymentCost.getShipperFeeCost(), paymentRate, 2));
        orderPaymentCost.setPayCost(MathUtil.multiply(orderPaymentCost.getActualTotalCost(), paymentRate, 2));
    }

    //生成送达退款单
    private Map<OrderPaymentCost, OrderRefundCost> generateReceiptRefundData(OrderPaymentCost orderPaymentCost) {
        Map<OrderPaymentCost, OrderRefundCost> paymentRefundMap = new HashMap<>();
        if (orderPaymentCost.getPaySite() != OrderPaymentCost.PaySite.receipt) return paymentRefundMap;
        Double overpaymentCost = MathUtil.subtract(orderPaymentCost.getSplitAlreadyPayCost(), orderPaymentCost.getActualTotalCost());
        if (overpaymentCost <= 0) return paymentRefundMap;
        return generateRefundData(paymentRefundMap, orderPaymentCost, overpaymentCost);
    }

    //生成清算退款单
    private Map<OrderPaymentCost, OrderRefundCost> generateClearingRefundData(OrderPaymentCost orderPaymentCost) {
        Map<OrderPaymentCost, OrderRefundCost> paymentRefundMap = new HashMap<>();
        if (orderPaymentCost.getPaySite() != OrderPaymentCost.PaySite.clearing) return paymentRefundMap;
        Double overpaymentCost = MathUtil.subtract(orderPaymentCost.getSplitAlreadyPayCost(), orderPaymentCost.getActualTotalCost());
        if (overpaymentCost <= 0) return paymentRefundMap;
        //查询收货支付单是否足够退款
        OrderPaymentCost receiptOrderPaymentCost = getOrderPaymentByTransitOrderId(orderPaymentCost.getTransitOrderId(), OrderPaymentCost.PaySite.receipt);
        if (receiptOrderPaymentCost.getPayCost() > overpaymentCost) {
            paymentRefundMap.put(receiptOrderPaymentCost, calculateOrderRefundCost(overpaymentCost, receiptOrderPaymentCost));
            return paymentRefundMap;
        }
        //收货支付单不够退款，先全退收货支付，然后再退发货支付单
        paymentRefundMap.put(receiptOrderPaymentCost, calculateOrderRefundCost(receiptOrderPaymentCost.getPayCost(), receiptOrderPaymentCost));
        //计算收货支付单需要退款金额
        Double overReceiptPaymentCost = MathUtil.subtract(overpaymentCost, receiptOrderPaymentCost.getPayCost());
        return generateRefundData(paymentRefundMap, orderPaymentCost, overReceiptPaymentCost);
    }

    //公共部分，多付退款逻辑
    private Map<OrderPaymentCost, OrderRefundCost> generateRefundData(Map<OrderPaymentCost, OrderRefundCost> paymentRefundMap, OrderPaymentCost orderPaymentCost, Double overpaymentCost) {
        //查询发货支付单是否足够退款
        OrderPaymentCost deliveryOrderPaymentCost = getOrderPaymentByTransitOrderId(orderPaymentCost.getTransitOrderId(), OrderPaymentCost.PaySite.delivery);
        if (deliveryOrderPaymentCost.getPayCost() > overpaymentCost) {
            paymentRefundMap.put(deliveryOrderPaymentCost, calculateOrderRefundCost(overpaymentCost, deliveryOrderPaymentCost));
            return paymentRefundMap;
        }
        //发货支付不够退款，先全退发货支付，然后再退抢单支付单 抢单支付单
        paymentRefundMap.put(deliveryOrderPaymentCost, calculateOrderRefundCost(deliveryOrderPaymentCost.getPayCost(), deliveryOrderPaymentCost));
        //计算抢单支付单需要退款金额
        Double overDeliveryPaymentCost = MathUtil.subtract(overpaymentCost, deliveryOrderPaymentCost.getPayCost());
        OrderPaymentCost robOrderPaymentCost = getOrderPaymentByRobOrderId(orderPaymentCost.getRobOrderId());
        if (robOrderPaymentCost.getPayCost() > overDeliveryPaymentCost) {
            paymentRefundMap.put(robOrderPaymentCost, calculateOrderRefundCost(overDeliveryPaymentCost, robOrderPaymentCost));
            return paymentRefundMap;
        }
        //抢单支付单还是不够扣款，先全退抢单支付单，然后再退货单支付单
        paymentRefundMap.put(robOrderPaymentCost, calculateOrderRefundCost(robOrderPaymentCost.getPayCost(), robOrderPaymentCost));
        //计算货单支付单需要退款金额
        Double overRobPaymentCost = MathUtil.subtract(overDeliveryPaymentCost, robOrderPaymentCost.getPayCost());
        OrderPaymentCost goodsOrderPaymentCost = getOrderPaymentByGoodsOrderId(orderPaymentCost.getGoodsOrderId());
        if (goodsOrderPaymentCost.getPayCost() > overRobPaymentCost) {
            paymentRefundMap.put(goodsOrderPaymentCost, calculateOrderRefundCost(overRobPaymentCost, goodsOrderPaymentCost));
            return paymentRefundMap;
        }
        throw new BusinessException("订单退款业务发生严重错误，支付单数据可能被手动篡改！");
    }

    //根据退款总费用计算各个费用退款金额
    private OrderRefundCost calculateOrderRefundCost(Double overPaymentCost, OrderPaymentCost orderPaymentCost) {
        Double refundRate = MathUtil.divide(overPaymentCost, orderPaymentCost.getPayCost(), 2);
        OrderRefundCost orderRefundCost = new OrderRefundCost();

        orderRefundCost.setShouldInsuranceCost(MathUtil.multiply(orderPaymentCost.getPayInsuranceCost(), refundRate,2));
        orderRefundCost.setShouldAdditionalCost(MathUtil.multiply(orderPaymentCost.getPayAdditionalCost(), refundRate,2));
        orderRefundCost.setShouldTransportCost(MathUtil.multiply(orderPaymentCost.getPayTransportCost(), refundRate,2));
        orderRefundCost.setShouldTaxCost(MathUtil.multiply(orderPaymentCost.getPayTaxCost(), refundRate,2));
        orderRefundCost.setShouldShipperFeeCost(MathUtil.multiply(orderPaymentCost.getPayShipperFeeCost(), refundRate,2));
        orderRefundCost.setShouldPayCost(overPaymentCost);

        orderRefundCost.setRefundInsuranceCost(MathUtil.multiply(orderPaymentCost.getPayInsuranceCost(), refundRate,2));
        orderRefundCost.setRefundAdditionalCost(MathUtil.multiply(orderPaymentCost.getPayAdditionalCost(), refundRate,2));
        orderRefundCost.setRefundTransportCost(MathUtil.multiply(orderPaymentCost.getPayTransportCost(), refundRate,2));
        orderRefundCost.setRefundTaxCost(MathUtil.multiply(orderPaymentCost.getPayTaxCost(), refundRate,2));
        orderRefundCost.setRefundShipperFeeCost(MathUtil.multiply(orderPaymentCost.getPayShipperFeeCost(), refundRate,2));
        orderRefundCost.setRefundCost(overPaymentCost);
        return orderRefundCost;
    }

    //获取可行的结算方式
    //如果结算方式==定价
    private GoodsOrder.SettlementType getAutSettlementType(GoodsOrder.SettlementType settlementType, OrderPaymentCost.PaySite paySite) {
        GoodsOrder.SettlementType minSettlementType = GoodsOrder.SettlementType.assignWav;
        if (paySite == OrderPaymentCost.PaySite.delivery) minSettlementType = GoodsOrder.SettlementType.deliverWav;
        if (paySite == OrderPaymentCost.PaySite.receipt) minSettlementType = GoodsOrder.SettlementType.arriveWav;
        if (paySite == OrderPaymentCost.PaySite.clearing) minSettlementType = GoodsOrder.SettlementType.gatherTotal;
        //### 实际结算方式还未开始时，暂时使用最近的结算方式
        if (settlementType.index > minSettlementType.index) return minSettlementType;
        return settlementType;
    }

}
